home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- #
- # Apple Products Presents
- #
- # S U R F E R ----- A CommToolbox Sample Application
- # by Alex Kazim
- #
- # Based on the MacDTS Simple Sample Application
- #
- # Surfer.c - C Source
- #
- # Copyright © 1988-9 Apple Computer, Inc.
- # All rights reserved.
- #
- # Versions: Sample 1.0 08/88
- # Sample 1.01 11/88
- #
- # Surfer 1.0 10/89
- # Surfer 1.01 02/90
- ------------------------------------------------------------------------------*/
-
- /*
- REVISION HISTORY
-
- 9/26/89 kaz • changed case on constants to match documentation
- • Fixed error handling to only call xxEvent() if the
- target of the event is a tool window
- • Initializes gBuffer according to sizes[cmDataIn]
- after the _CMNew call
-
- 10/1/89 kaz • TermGetConnEnvirons() and FTGetConnEnvirons() were
- merged into one routine: ToolGetConnEnvirons()
- • IsAppWindow() uses _GetWRefCon instead of looking
- at the windowrecord refcon field.
- • Moved DiposePtr(gBuffer) to CloseWindow()
- • _HLock/_HUnlock all the tool handles
- • Took out alerts to let the tools handle it themselves
-
- 10/4/89 kaz • Was forgetting to clear gStartFT after a receive
-
- 1/9/90 kaz • Fixed a bug that didn't call _TMIdle if there was
- a same-circuit file transfer in progress. _TMIdle
- will be called regardless.
- • TermSendProc() will not send any data if there is
- a same-circuit file transfer in progress.
-
- 1/29/90 kaz • Allocates the buffer by looking at the bufSizes in
- the ConnRecord instead of assuming my Buffer max.
- • Cleaned up TermRecvProc() to be less confusing
-
- 2/14/90 kaz • Was _HLocking the term handle before _TMChoose instead
- of _HUnlocking it.
-
- 8/7/92 cnc • Ported to C from Pascal
- */
-
-
- #include <CommResources.h>
- #include <Terminals.h>
- #include <Connections.h>
- #include <FileTransfers.h>
- #include <Types.h>
- #include <Errors.h>
- #include <Windows.h>
- #include <Fonts.h>
- #include <Menus.h>
- #include <Memory.h>
- #include <Desk.h>
- #include <DiskInit.h>
- #include <ToolUtils.h>
- #include <QuickDraw.h>
-
- #include "Surfer.h"
-
- #ifndef FALSE
- #define FALSE 0
- #define TRUE 1
- #endif
-
- const Str32 kDefaultTermTool = "\pVT102 Tool"; // what tools we want first
- const Str32 kDefaultFTTool = "\pText Tool";
- const Str32 kDefaultConnTool = "\pSerial Tool";
-
- Boolean gHasWaitNextEvent; //set up by Initialize
- Boolean gInBackground; //maintained by Initialize and DoEvent
-
- TermHandle gTerm; // Tool Handles: Single Session
- ConnHandle gConn;
- FTHandle gFT;
-
- Ptr gBuffer; // Data Storage for Reads/Writes
-
- long gFTSearchRefNum; // Auto-Initiate File Transfers
- Boolean gStartFT; // Auto-start
- Boolean gWasFT; // In progress
-
-
- pascal void AlertUser(Str255 msg, Boolean fatal);
- pascal void Terminate(void);
-
- /*******************************************************************
- * TrapAvailable - Checks to see if a given trap is implemented
- *
- * tNumber - trap number
- * tType - type of trap
- *
- * returns - true if it exists
- *
- **********************************************************************/
- #pragma segment Initialize
- pascal Boolean TrapAvailable(short tNumber, TrapType tType)
- {
- short unImplemented;
-
- if (tType == OSTrap)
- unImplemented = _UnimplementedOSTrap;
- else
- unImplemented = _UnimplementedToolTrap;
-
- return NGetTrapAddress(tNumber, tType) != GetTrapAddress(unImplemented);
- } //TrapAvailable
-
-
- /*******************************************************************
- * TermSendProc - Sends the data out the connection
- *
- * thePtr - the data to send
- * theSize - bytes to send
- * refcon - terminal tool refcon
- * flags - connection flags
- *
- * returns - bytes sent
- *
- **********************************************************************/
- #pragma segment Main
- pascal long TermSendProc(Ptr thePtr,long theSize, long refcon, short flags)
- {
- #pragma unused (refcon)
-
- OSErr theErr;
- long retCode = 0; // Assume the worst
-
- if (gConn != NULL)
- {
-
- // If there's a file transfer in progress && it's
- // over our connection, then don't send the data.
-
- if (gFT != NULL)
- {
- if (((((*gFT)->flags) & ftIsFTMode) != 0) &&
- ((((*gFT)->attributes) & ftSameCircuit) != 0))
- return retCode;
- }
-
- theErr = CMWrite(gConn, thePtr, &theSize, cmData, FALSE, NULL, 0, flags);
-
- if (theErr == noErr)
- retCode = theSize; // If ok, we sent all
-
- } // Good Connection
-
- return retCode;
- } // TermSendProc
-
-
- /*******************************************************************
- * TermRecvProc - Gets the data from the connection and sends
- * it to the terminal tool.
- *
- * NOTE - This is !a callback proc, but does
- * resemble the functionality.
- *
- *
- **********************************************************************/
- #pragma segment Main
- pascal void TermRecvProc(void)
- {
- CMErr theErr;
- CMStatFlags status;
- CMBufferSizes sizes;
- CMFlags flags;
- long bytesEaten;
-
- if ((gConn != NULL) && (gTerm != NULL))
- {
-
- // Get the state of the connection
- theErr = CMStatus(gConn, sizes, &status);
-
- if (theErr == noErr)
- {
-
- // Route the data if we have any
- if ((((status & cmStatusOpen)+ cmStatusDataAvail) != 0) &&
- (sizes[cmDataIn] != 0))
- {
-
- // Tell the tool to get the data
- theErr = CMRead(gConn, gBuffer, &sizes[cmDataIn], cmData, FALSE,
- NULL, 0, &flags);
-
- // Send data to the terminal
- if (theErr == noErr)
- bytesEaten = TMStream(gTerm,gBuffer, sizes[cmDataIn],flags);
-
- // Could check bytesEaten vs. sizes[cmDataIn]
-
- } // sizes != 0
-
- } // Good Status
-
- if (theErr != noErr)
- ; // Connection tool will alert the user on an error
-
- } // Good term && conn
-
- } // TermRecvProc
-
-
-
- /*******************************************************************
- * ToolGetConnEnvirons - Gets the connection environs for
- * the FT or Term tool
- *
- * refcon - the tool refcon
- * theEnvirons - the environment
- *
- * returns - an environment error
- *
- **********************************************************************/
- #pragma segment Main
- pascal OSErr ToolGetConnEnvirons(long refcon, ConnEnvironRec *theEnvirons)
- {
- #pragma unused (refcon)
-
- OSErr retCode = envNotPresent; // pessimism
-
- // Version is set by the tool
- if (gConn != NULL)
- retCode = CMGetConnEnvirons(gConn, theEnvirons);
-
- return retCode;
- } // TermGetConnEnvirons
-
-
-
- /*******************************************************************
- * FTSendProc - Sends data during a file transfer
- *
- * thePtr - data to send
- * theSize - bytes to send
- * refcon - the FTtool refcon
- * channel - which channel to use
- * flags - connection flags
- *
- * returns - bytes sent
- *
- **********************************************************************/
- #pragma segment Main
- pascal long FTSendProc(thePtr, theSize, refcon, channel, flags)
- Ptr thePtr;
- long theSize;
- long refcon;
- CMChannel channel;
- short flags;
- {
- #pragma unused (refcon)
-
- CMErr theErr;
- long retCode = 0; // Assume the worst
-
- if (gConn != NULL) {
- // Send the data
- theErr = CMWrite(gConn, thePtr, &theSize, channel, FALSE, NULL, 0, flags);
- if (theErr == noErr)
- retCode = theSize; // if ok, we sent all
-
- } // Good Connection
-
- return retCode;
- } // FTSendProc
-
-
-
- /*******************************************************************
- * FTReceiveProc - Gets data during a file transfer
- *
- * thePtr - place for data
- * theSize - bytes to get
- * refcon - the FTtool refcon
- * channel - which channel to use
- * flags - connection flags
- *
- * returns - bytes gotten
- *
- **********************************************************************/
- #pragma segment Main
- pascal long FTReceiveProc(thePtr, theSize, refcon, channel, flags)
- Ptr thePtr;
- long theSize;
- long refcon;
- CMChannel channel;
- CMFlags *flags;
- {
- #pragma unused (refcon)
-
- CMErr theErr;
- long retCode = 0; // Assume the worst
-
- if (gConn != NULL)
- {
- // Read all the data
- theErr = CMRead(gConn, thePtr, &theSize, channel, FALSE, NULL, 0, flags);
- if (theErr == noErr)
- retCode = theSize; // if ok, we got all
-
- } // Good Connection
-
- return retCode;
- } // FTReceiveProc
-
-
- /*******************************************************************
- * AutoRecCallback - Sets the file transfer flag if an auto-
- * receive string was found.
- *
- * theConn - which connection tool found it
- * data - ptr to last character in the match
- * refNum - which search was found
- *
- **********************************************************************/
- #pragma segment Main
- pascal void AutoRecCallback(ConnHandle theConn, Ptr data, long refNum)
- {
- #pragma unused (theConn, data)
-
- // We can't call _FTStart or _CMRemoveSearch here as
- // this proc might be called from Interrupt level
-
- if (gFTSearchRefNum == refNum)
- gStartFT = TRUE; // Set the flag to call FTStart in Idle
- } // AutoRecCallBack
-
-
-
- /*******************************************************************
- * AddFTSearch - Checks to see if the file transfer has an
- * auto-receive string, and adds a search to
- * find it.
- *
- **********************************************************************/
- #pragma segment Main
- pascal void AddFTSearch(void)
- {
- Str255 tempStr; // the string to look for
-
- if ((gFT != NULL) && (gConn != NULL))
- {
- if ((*gFT)->autoRec[0]) // Do I need to add a search
- {
- BlockMove((*gFT)->autoRec, tempStr, (*gFT)->autoRec[0] + 1);
- gFTSearchRefNum = CMAddSearch(gConn, tempStr, cmSearchSevenBit, &AutoRecCallback);
- if (gFTSearchRefNum == -1)
- {
- AlertUser("\pCouldn't add stream search",FALSE);
- gFTSearchRefNum = 0;
- }
- } // can autoreceive
-
- } // good FT and Conn
-
- } // AddFTSearch
-
-
-
- /*******************************************************************
- * DoSend - Initiates a File Transfer send from the menu command
- *
- **********************************************************************/
- #pragma segment Main
- pascal void DoSend(void)
- {
- SFReply theReply; // File Info
- Point where; // Top Left of File dialog
- short numTypes; // File Types to display
- SFTypeList typeList;
- FTErr anyErr; // Error handler
-
- if (gFT != NULL)
- {
- SetPt(&where, 100, 100);
-
- // If the FT tool can only send Text files, then
- // only display text files, else display all types
-
- // Check to see if Text Only flag is set
- if ((((*gFT)->attributes) & ftTextOnly) != 0)
- {
- typeList[0] = 'TEXT';
- numTypes = 1;
- }
- else
- numTypes = -1;
-
- SFGetFile(where, "\pFile to Send", NULL, numTypes, typeList, NULL, &theReply);
-
- // Did the user hit OK or Cancel
- if (theReply.good)
- {
- // Transfer the file TO the remote
- anyErr = FTStart(gFT, ftTransmitting, &theReply);
-
- if (anyErr != noErr)
- ; // File Transfer tool will alert user on an error
-
- } // Good file
- } // Good FTHandle
-
- } // DoSend
-
-
- /*******************************************************************
- * DoReceive - Initiates a File Transfer receive from the menu
- *
- **********************************************************************/
- #pragma segment Main
- pascal void DoReceive(void)
- {
- SFReply theReply; // File Info
- OSErr anyErr; // Errors on Start
-
- if (gFT != NULL)
- {
-
- // Let the FT tool use its own default file info
- theReply.vRefNum = 0;
- theReply.fName[0] = 0;
- theReply.good = TRUE;
-
- gStartFT = FALSE; // Shut the flag down
-
- // We remove the search temporarily in case it comes
- // across during the transfer. Will be re-added in the
- // idle loop once the transfer is completed
-
- if (gConn != NULL)
- if (((*gFT)->autoRec[0] != 0) && (gFTSearchRefNum != 0))
- {
- CMRemoveSearch(gConn, gFTSearchRefNum);
- gFTSearchRefNum = 0; // We found it already
- }
-
- // Start receiving the file
- // The rest gets transferred in the Idle loop
-
- anyErr = FTStart(gFT, ftReceiving, &theReply);
-
- if (anyErr != noErr)
- ; // File Transfer tool will alert user on an error
-
- } // Good Handle
-
- } // DoReceive
-
-
- /*******************************************************************
- * IsDAWindow - Checks to see if a window belongs to a desk acc.
- *
- * window - the culprit
- *
- * returns - true if it's a DA
- *
- **********************************************************************/
- #pragma segment Main
- pascal Boolean IsDAWindow(WindowPtr window)
- {
- if (window == NULL)
- return FALSE;
- else // DA windows have negative windowKinds
- return ((WindowPeek) window)->windowKind < 0;
- } //IsDAWindow
-
-
-
- /*******************************************************************
- * IsAppWindow - Checks to see if a window belongs to our app
- *
- * window - the culprit
- *
- * returns - true if it's an app window
- *
- **********************************************************************/
- #pragma segment Main
- pascal Boolean IsAppWindow(WindowPtr window)
- {
- long theRefCon;
-
- // Check the userkind and the refcon for tool windows
- if (window == NULL)
- return FALSE;
- else
- {
- theRefCon = GetWRefCon(window);
- return
- ((((WindowPeek) window)->windowKind >= userKind) ||
- (((WindowPeek) window)->windowKind == dialogKind)) &&
- (gTerm != (TermHandle) theRefCon) &&
- (gConn != (ConnHandle) theRefCon) &&
- (gFT != (FTHandle) theRefCon);
- }
- } //IsAppWindow
-
-
-
- /*******************************************************************
- * AlertUser - Informs the user of any errors
- *
- * msg - The string to display
- * fatal - Exit if this is a fatal error
- *
- **********************************************************************/
- #pragma segment Main
- pascal void AlertUser(Str255 msg, Boolean fatal)
- {
- short itemHit;
-
- SetCursor(&qd.arrow);
-
- ParamText(msg,"\p","\p","\p");
- itemHit = Alert(rUserAlert, NULL);
-
- if (fatal)
- Terminate();
- } // AlertUser
-
-
-
- /*******************************************************************
- * OpenConnection - Initiates a connection
- *
- **********************************************************************/
- #pragma segment Main
- pascal void OpenConnection(void)
- {
- CMErr theErr;
- CMBufferSizes sizes; // Connection Tool data
- CMStatFlags status;
-
- if (gConn != NULL)
- {
- // Get connection info
- theErr = CMStatus(gConn, sizes, &status);
-
- if (theErr == noErr)
- {
- // If it isn't already open, then open it
- if ((status & (cmStatusOpen + cmStatusOpening)) == 0)
- theErr = CMOpen(gConn, FALSE, NULL, 0);
- }
-
- if (theErr != noErr)
- ; // Conn tool will alert user on an error
- }
- } //OpenConnection
-
-
-
- /*******************************************************************
- * CloseConnection - Kills a connection
- *
- **********************************************************************/
- #pragma segment Main
- pascal void CloseConnection(void)
- {
- CMErr theErr;
- CMBufferSizes sizes; // Connection Tool data
- CMStatFlags status;
-
- // Kill the current connection
- if (gConn != NULL)
- {
- theErr = CMStatus(gConn, sizes, &status);
-
- // If it's open, then close it
- if (theErr == noErr)
- if ((status & (cmStatusOpen+ cmStatusOpening)) != 0)
- theErr = CMClose(gConn, FALSE, NULL, 0, TRUE);
-
- if (theErr != noErr)
- ; // Conn tool will alert user on an error
-
- }
-
- } //CloseConnection
-
-
-
- /*******************************************************************
- * DoCloseWindow - Closes the window
- *
- * window - the culprit
- *
- * returns - always returns true
- *
- **********************************************************************/
- #pragma segment Main
- pascal Boolean DoCloseWindow(WindowPtr window)
- {
- Boolean retCode = TRUE;
-
- if (IsDAWindow(window))
- CloseDeskAcc(((WindowPeek) window)->windowKind);
- else
- if (IsAppWindow(window))
- {
-
- CloseConnection(); // Stop what we're doin'
-
- // Dispose of all the tools
- if (gTerm != NULL)
- {
- HUnlock((Handle) gTerm);
- TMDispose(gTerm);
- }
-
- if (gFT != NULL)
- {
- HUnlock((Handle) gFT);
- FTDispose(gFT);
- }
-
- if (gConn != NULL)
- {
- HUnlock((Handle) gConn);
- CMDispose(gConn);
- }
-
- if (gBuffer != NULL) // Clean up our buffer
- DisposPtr(gBuffer);
-
- DisposeWindow(window);
- } // App Window
-
- return retCode;
- } //DoCloseWindow
-
-
- /*******************************************************************
- * FindToolID - Tries to get the default tool proc id,
- * otherwise, gets the first one it finds.
- *
- * toolClass - What kind of tool: term, ft, conn
- *
- * returns - the tool proc id or -1 if not found
- *
- **********************************************************************/
- #pragma segment Main
- pascal short FindToolID(OSType toolClass)
- {
- Str255 toolName; // tool file name
- OSErr anyErr;
- short procID; // tool fref number
-
- procID = -1; // Unknown tool
-
- switch (toolClass)
- {
- case classTM:
- // If it can't get the default, get the 1st
- BlockMove(kDefaultTermTool, toolName, kDefaultTermTool[0] + 1); //VT102 Tool
- procID = TMGetProcID(toolName);
-
- if (procID == -1)
- {
- anyErr = CRMGetIndToolName(toolClass, 1, toolName);
- if (anyErr == noErr)
- procID = TMGetProcID(toolName);
- }
- break;
-
- case classCM:
- // If it can't get the default, get the 1st
- BlockMove(kDefaultConnTool, toolName, kDefaultConnTool[0] + 1);
- procID = CMGetProcID(toolName);
-
- if (procID == -1)
- {
- anyErr = CRMGetIndToolName(toolClass,1,toolName);
- if (anyErr == noErr)
- procID = CMGetProcID(toolName);
- }
- break;
-
- case classFT:
- // If it can't get the default, get the 1st
- BlockMove(kDefaultFTTool, toolName, kDefaultFTTool[0] + 1);
- procID = FTGetProcID(toolName);
-
- if (procID == -1)
- {
- anyErr = CRMGetIndToolName(toolClass,1,toolName);
- if (anyErr == noErr)
- procID = FTGetProcID(toolName);
- }
- break;
- }
-
- return procID;
- } //FindToolID
-
-
- /*******************************************************************
- * DoNewWindow - Gets the window and creates the session
- *
- * window - the culprit
- *
- * returns - always returns true
- *
- **********************************************************************/
- #pragma segment Main
- pascal Boolean DoNewWindow()
- {
- WindowPtr window; // the window to create
- Rect theRect; // for the terminal bounds
- short procID; // tool's ref number
- CMBufferSizes sizes; // requested size of the buffers
-
- // Get window
- window = GetNewWindow(rWindow, NULL, (WindowPtr) -1);
- SetPort(window);
-
- // TERMINAL TOOL
- procID = FindToolID(classTM);
- if (procID == -1)
- AlertUser("\pNo terminal tools found",TRUE);
-
- theRect = window->portRect;
-
- // Flags set to 0; no cacheProc, breakProc, or clikLoop;
- // refCon and UserData are 0.
- #ifdef THINK_C
- gTerm = TMNew(&theRect, &theRect, 0, procID, window, &TermSendProc,
- NULL, NULL, NULL, &ToolGetConnEnvirons, 0, 0);
- #else
- gTerm = TMNew(&theRect, &theRect, 0, procID, window, (TerminalSendProcPtr) &TermSendProc,
- NULL, NULL, NULL, (TerminalEnvironsProcPtr) &ToolGetConnEnvirons, 0, 0);
- #endif
- if (gTerm == NULL)
- AlertUser("\pCan't create a terminal tool",TRUE);
-
- MoveHHi((Handle) gTerm);
- HLock((Handle) gTerm);
-
- // CONNECTION TOOL
- procID = FindToolID(classCM);
- if (procID == -1)
- AlertUser("\pNo connection tools found",TRUE);
-
- sizes[cmDataIn] = kBufferSize;
- sizes[cmDataOut] = kBufferSize;
- sizes[cmCntlIn] = 0;
- sizes[cmCntlOut] = 0;
- sizes[cmAttnIn] = 0;
- sizes[cmAttnOut] = 0;
-
- // refCon and UserData are 0.
- gConn = CMNew(procID, cmData, sizes, 0, 0);
- if (gConn == NULL)
- AlertUser("\pCan't create a connection tool",TRUE);
-
- MoveHHi((Handle) gConn);
- HLock((Handle) gConn);
-
- // Allocate space for the read/writes using the number
- // returned by the connection tool
- gBuffer = NewPtr((*gConn)->bufSizes[cmDataIn]);
- if (MemError() != noErr)
- AlertUser("\pOut of memory",TRUE);
-
- // FILE TRANSFER TOOL
- procID = FindToolID(classFT);
- if (procID == -1)
- AlertUser("\pNo file transfer tools found",FALSE);
-
- // Flags set to 0, no read/write proc (let the tool use its own),
- // refCon and UserData are 0.
- #ifdef THINK_C
- gFT = FTNew(procID, 0, &FTSendProc, &FTReceiveProc, NULL, NULL,
- &ToolGetConnEnvirons, window, 0, 0);
- #else
- gFT = FTNew(procID, 0, (FileTransferSendProcPtr) &FTSendProc,
- (FileTransferReceiveProcPtr) &FTReceiveProc, NULL, NULL,
- (FileTransferEnvironsProcPtr) &ToolGetConnEnvirons, window, 0, 0);
- #endif
- if (gFT == NULL)
- AlertUser("\pCan't create a file transfer tool",TRUE);
-
- MoveHHi((Handle) gFT);
- HLock((Handle) gFT);
-
- gWasFT = FALSE; // FT in progress
- gStartFT = FALSE; // Auto-received string found
- gFTSearchRefNum = 0; // Clear the search refnum
-
- AddFTSearch(); // Look for the auto-receive string
-
- return TRUE;
- } //DoNewWindow
-
-
-
- /*******************************************************************
- * Initialize - Inits the various toolbox stuff
- *
- **********************************************************************/
-
- #pragma segment Initialize
- pascal void Initialize(void)
- {
- Handle menuBar;
- OSErr ignoreError;
- long total, contig;
- Boolean ignoreResult;
- EventRecord event;
- short count;
- SysEnvRec terraMac; //set up by Initialize
- short err;
-
- // Do we have Multifinder?
- gHasWaitNextEvent = TrapAvailable(_WaitNextEvent, ToolTrap);
- gInBackground = FALSE;
-
- // Standard Fare
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(NULL);
- InitCursor();
-
- // Bring us to the front
- for (count = 1; count <= 3; count++)
- ignoreResult = GetNextEvent(everyEvent, &event);
-
- // Does CommToolbox Exist?
- if (!TrapAvailable(_CommToolboxTrap, OSTrap))
- AlertUser("\pACK!! No CommToolbox",TRUE);
-
- // Check for System 6.0 or better, 64K ROM
- ignoreError = SysEnvirons(kSysEnvironsVersion, &terraMac);
-
- if ((terraMac.systemVersion < 0x0600) || (terraMac.machineType < 0))
- AlertUser("\pNeed System 6.0 or better",TRUE);
-
- // Check various memory configs
- if (FreeMem() < kMinHeap)
- AlertUser("\pOut of Memory",TRUE);
-
- PurgeSpace(&total, &contig);
- if (total < kMinSpace)
- AlertUser("\pOut of Memory",TRUE);
-
- // Load up the Communications Toolbox
- // Must Initialize CRM && CTBUtilities first
- err = InitCTBUtilities();
- err = InitCRM();
-
- err = InitTM(); // initializes the Terminal Manager
- if (err == tmNoTools)
- AlertUser("\pNo terminal tools found",TRUE);
-
- err = InitCM(); // initializes the Connection Manager
- if (err == cmNoTools)
- AlertUser("\pNo connection tools found",TRUE);
-
- err = InitFT(); // initializes the File Transfer Manager
- if (err == ftNoTools)
- AlertUser("\pNo file transfer tools found",FALSE);
-
- gTerm = NULL;
- gConn = NULL;
- gFT = NULL;
- gFTSearchRefNum = 0;
-
- if (!DoNewWindow())
- AlertUser("\pCan't create a session",TRUE);
-
- menuBar = GetNewMBar(rMenuBar); //read menus into menu bar
- if (menuBar == NULL)
- AlertUser("\pCan't get the menu bar",TRUE);
- SetMenuBar(menuBar); //install menus
- DisposHandle(menuBar);
-
- AddResMenu(GetMHandle(mApple), 'DRVR'); //add DA names to Apple menu
- DrawMenuBar();
- } //
-
-
- /*******************************************************************
- * Terminate - Cleans up and exits
- *
- **********************************************************************/
-
- #pragma segment Main
- pascal void Terminate(void)
- {
- WindowPtr aWindow; // the window to shut
- Boolean closed; // Are we done, yet
-
- // Close all the open windows
- closed = TRUE;
-
- aWindow = FrontWindow();
-
- do {
- if (aWindow != NULL)
- if (IsAppWindow(aWindow))
- closed = DoCloseWindow(aWindow);
-
- // Try the next window
- if (aWindow != NULL)
- aWindow = (WindowPtr) ((WindowPeek) aWindow)->nextWindow;
-
- } while (closed && (aWindow != NULL));
-
- if (closed)
- ExitToShell(); //exit if no cancellation
- } //Terminate
-
-
-
- /*******************************************************************
- * AdjustMenus - Enables && Disables items based on current state
- *
- **********************************************************************/
-
- #pragma segment Main
- pascal void AdjustMenus(void)
- {
- WindowPtr window; // whose in front
- MenuHandle menu; // the menu to manipulate
- CMErr theErr;
- CMBufferSizes sizes; // Connection tool data
- CMStatFlags status;
-
- window = FrontWindow();
-
- menu = GetMHandle(mFile);
- if (menu == NULL)
- AlertUser("\pCan't get menu resource", TRUE);
-
- if (gConn != NULL)
- {
- theErr = CMStatus(gConn, sizes, &status);
- if (theErr == noErr)
- {
- if (!IsDAWindow(window))
- {
- SetItem(menu,iOpen,"\pOpen Connection");
- SetItem(menu,iClose,"\pClose Connection");
-
- // Let the menu show the proper state of the union
- if ((status & (cmStatusOpen+ cmStatusOpening)) == 0)
- {
- EnableItem(menu, iOpen);
- DisableItem(menu, iClose);
- }
- else
- {
- DisableItem(menu, iOpen);
- EnableItem(menu, iClose);
- }
-
- // Check state of the FT tool to Enable send/receive
- DisableItem(menu,iSendFile);
- DisableItem(menu,iReceiveFile);
-
- if (gFT != NULL)
- {
- if (((*gFT)->attributes & ftSendDisable) == 0)
- EnableItem(menu,iSendFile);
-
- if (((*gFT)->attributes & ftReceiveDisable) == 0)
- EnableItem(menu,iReceiveFile);
- }
- }
- else
- {
- // Set for desk accesories
- SetItem(menu,iOpen,"\pOpen");
- SetItem(menu,iClose,"\pClose");
- DisableItem(menu, iOpen);
- EnableItem(menu,iClose);
- DisableItem(menu,iSendFile);
- DisableItem(menu,iReceiveFile);
- }
-
- } // good status
- } // good connection
-
-
- menu = GetMHandle(mEdit);
- if (menu == NULL)
- AlertUser("\pCan't get menu resource", TRUE);
-
- if (IsDAWindow(window))
- { // DAs might use this menu
- EnableItem(menu, iUndo);
- EnableItem(menu, iCut);
- EnableItem(menu, iCopy);
- EnableItem(menu, iPaste);
- EnableItem(menu, iClear);
- }
- else
- { // but we don't use it yet
- DisableItem(menu, iUndo);
- DisableItem(menu, iCut);
- DisableItem(menu, iCopy);
- DisableItem(menu, iClear);
- DisableItem(menu, iPaste);
- }
-
- menu = GetMHandle(mSettings);
- if (menu == NULL)
- AlertUser("\pCan't get menu resource", TRUE);
-
- if (!IsDAWindow(window))
- {
- // Enable if we're front
- EnableItem(menu, iConnection);
- EnableItem(menu, iFileTransfer);
- EnableItem(menu, iTerminal);
- }
- else
- {
- DisableItem(menu, iConnection);
- DisableItem(menu, iFileTransfer);
- DisableItem(menu, iTerminal);
- }
-
- } //AdjustMenus
-
-
- /*******************************************************************
- * DoToolMenu - Tries to give the menu to the tool
- *
- * menuID - the menu info from DoMenuCommand
- * menuItem
- *
- * returns - TRUE if a tool handled the menu
- *
- **********************************************************************/
- #pragma segment Main
- pascal Boolean DoToolMenu(int menuID, int menuItem)
- {
- if (gTerm != NULL)
- if (TMMenu(gTerm, menuID, menuItem))
- return TRUE;
-
- if (gConn != NULL)
- if (CMMenu(gConn, menuID, menuItem))
- return TRUE;
-
- if (gFT != NULL)
- if (FTMenu(gFT, menuID, menuItem))
- return TRUE;
-
- return FALSE;
- } //DoToolMenu
-
-
- /*******************************************************************
- * DoMenuCommand - Executes a menu command
- *
- * menuResult - the menu id and item number
- *
- **********************************************************************/
-
- #pragma segment Main
- pascal void DoMenuCommand(long menuResult)
- {
- short menuID; // resource ID of the selected menu
- short menuItem; // item number of the selected menu
- short itemHit; // for the alert
- Str255 daName; // for opening desk accesories
- short daRefNum;
- Boolean handledByDA; // DA edit menu handling
- Boolean ignore;
- Point where; // For choose dialog
- short result;
-
- menuID = HiWord(menuResult); //use built-ins (for efficiency)...
- menuItem = LoWord(menuResult); //to get menu item number and menu number
-
- // First see if the menu belonged to a tool
-
- if (!DoToolMenu(menuID,menuItem))
- switch (menuID)
- {
- case mApple:
- switch (menuItem)
- {
- case iAbout:
- //bring up alert for About
- itemHit = Alert(rAboutAlert, NULL);
- break;
-
- default:
- // all non-About items in this menu are DAs
- GetItem(GetMHandle(mApple), menuItem, daName);
- daRefNum = OpenDeskAcc(daName);
- break;
- }
-
- case mFile:
- switch (menuItem)
- {
- case iOpen:
- if (!IsDAWindow(FrontWindow()))
- OpenConnection();
- break;
-
- case iClose:
- if (IsDAWindow(FrontWindow()))
- ignore = DoCloseWindow(FrontWindow());
- else
- CloseConnection();
- break;
-
- case iSendFile:
- if (!IsDAWindow(FrontWindow()))
- DoSend();
- break;
-
- case iReceiveFile:
- if (!IsDAWindow(FrontWindow()))
- DoReceive();
- break;
-
- case iQuit:
- Terminate();
- break;
- }
-
- case mEdit:
- //call SystemEdit for DA editing && MultiFinder
- //since we don't do any editing
- handledByDA = SystemEdit(menuItem-1);
- break;
-
- case mSettings:
- switch (menuItem)
- {
- case iConnection:
- if (gConn != NULL)
- {
- HUnlock((Handle) gConn);
-
- SetPt(&where,10,40);
-
- result = CMChoose(&gConn, where, NULL);
-
- switch (result)
- {
- case chooseDisaster:
- case chooseFailed:
- AlertUser("\pConnection choose failed",
- (result == chooseDisaster));
- break;
- case chooseOKMajor:
- AddFTSearch();
- break;
- }
-
- HLock((Handle) gConn);
- }
- break;
-
- case iFileTransfer:
- if (gFT != NULL)
- {
- HUnlock((Handle) gFT);
-
- SetPt(&where,10,40);
- result = FTChoose(&gFT, where, NULL);
-
- switch (result)
- {
- case chooseDisaster:
- case chooseFailed:
- AlertUser("\pFile Transfer choose failed",
- (result == chooseDisaster));
- break;
- case chooseOKMinor:
- case chooseOKMajor:
- // Get rid of the old search
- if ((gFTSearchRefNum != 0) && (gConn != NULL))
- CMRemoveSearch(gConn,gFTSearchRefNum);
- gFTSearchRefNum = 0;
-
- AddFTSearch(); // Add the new FT tool search
- break;
- }
-
- HLock((Handle) gFT);
- } // good ft
- break;
-
- case iTerminal:
- if (gTerm != NULL)
- {
- HUnlock((Handle) gTerm);
-
- SetPt(&where,10,40);
- result = TMChoose(&gTerm, where, NULL);
-
- if ((result < 0))
- AlertUser("\pTerminal choose failed",(result == chooseDisaster));
-
- HLock((Handle) gTerm);
- }
- break;
-
- } // case menuitem
-
- } // case menuid
-
- HiliteMenu(0); //unhighlight what MenuSelect (or MenuKey) hilited
- } //DoMenuCommand
-
-
- /*******************************************************************
- * DoUpdate - Updates the window
- *
- * window - target of teh update
- *
- **********************************************************************/
- #pragma segment Main
- pascal void DoUpdate(WindowPtr window)
- {
- RgnHandle savedClip; // saved info for reset later
- GrafPtr savedPort;
-
- if (IsAppWindow(window))
- {
- GetPort(&savedPort);
- SetPort(window);
-
- // Clip to the window content
- savedClip = NewRgn();
- GetClip(savedClip);
- ClipRect(&window->portRect);
-
- BeginUpdate(window);
- if (gTerm != NULL) // Update the terminal tool
- TMUpdate(gTerm, window->visRgn);
- EndUpdate(window);
-
- SetClip(savedClip);
- DisposeRgn(savedClip);
-
- SetPort(savedPort);
- }
- } //DoUpdate
-
-
- /*******************************************************************
- * DoResume - Suspends/Resumes the window
- *
- * becomingActive - Resume or Suspend
- *
- **********************************************************************/
-
- #pragma segment Main
- pascal void DoResume(Boolean becomingActive)
- {
- WindowPtr theWindow;
- GrafPtr savedPort;
-
- // Since the front window could be a tool window, we need
- // to find the app window by walking the list so we can
- // send resume messages to the tools
-
- GetPort(&savedPort);
-
- theWindow = FrontWindow();
-
- while (theWindow != NULL)
- {
- if (IsAppWindow(theWindow))
- {
- SetPort(theWindow);
-
- /* Tools need to adjust their menus, text selection, etc */
- if (gTerm != NULL)
- TMResume(gTerm, becomingActive);
-
- if (gConn != NULL)
- CMResume(gConn, becomingActive);
-
- if (gFT != NULL)
- FTResume(gFT, becomingActive);
- } // app window
-
- // Try the next window
- theWindow = (WindowPtr) ((WindowPeek) theWindow)->nextWindow;
- }
-
- SetPort(savedPort);
-
- } //DoResume
-
-
- /*******************************************************************
- * DoActivate - (De)Activates the window
- *
- * window - target of the update
- * becomingActive - Activate or Deactivate
- *
- **********************************************************************/
-
- #pragma segment Main
- pascal void DoActivate(WindowPtr window, Boolean becomingActive)
- {
- if (IsAppWindow(window))
- {
- SetPort(window);
-
- /* Tools need to adjust their menus, text selection, etc */
- if (gTerm != NULL)
- TMActivate(gTerm, becomingActive);
-
- if (gConn != NULL)
- CMActivate(gConn, becomingActive);
-
- if (gFT != NULL)
- FTActivate(gFT, becomingActive);
- }
-
- } //DoActivate
-
-
- /*******************************************************************
- * AdjustCursor - Updates mouse cursor depending on location
- *
- * mouse - the location of the mouse (global coords)
- *
- **********************************************************************/
- #pragma segment Main
- pascal void AdjustCursor(Point mouse)
- {
- WindowPtr window;
-
- window = FrontWindow(); // Adjust only if front
-
- if ((!gInBackground) && (IsAppWindow(window)))
- {
- GlobalToLocal(&mouse);
-
- // If it's outside the content, set to arrow
- // otherwise the terminal tool will handle it
-
- if (gTerm != NULL)
- if (!PtInRect(mouse,&((*gTerm)->viewRect)))
- InitCursor();
-
- } // app window
-
- } //AdjustCursor
-
-
- /*******************************************************************
- * DoToolEvent - Tries to pass the event to a tool if the
- * window is a tool window
- *
- * event - the event received
- *
- * returns - True if the tool handled it
- *
- **********************************************************************/
- #pragma segment Main
- pascal Boolean DoToolEvent(EventRecord event, WindowPtr window)
- {
- Boolean retCode;
-
- if (window != NULL)
- {
- retCode = TRUE;
-
- if ((gFT != NULL) && (gFT == (FTHandle) GetWRefCon(window)))
- FTEvent(gFT, &event);
- else
- if ((gConn != NULL) && (gConn == (ConnHandle) GetWRefCon(window)))
- CMEvent(gConn, &event);
- else
- if ((gTerm != NULL) && (gTerm == (TermHandle) GetWRefCon(window)))
- TMEvent(gTerm, &event);
- else
- retCode = FALSE;
- }
- else
- retCode = FALSE;
-
- return retCode;
- } //DoToolEvent
-
-
-
- /*******************************************************************
- * DoEvent - Updates mouse cursor depending on location
- *
- * event - the event to handle
- *
- **********************************************************************/
- #pragma segment Main
- pascal void DoEvent(EventRecord event)
- {
- int part; // where the mouse click was
- short err;
- WindowPtr window; // the click's window
- char key; // the letter typed
- Point aPoint; // for the dialog top left
- long result; // result from MenuKey
- Boolean processed; // Did the App handle it
-
- switch (event.what)
- {
- case mouseDown:
- part = FindWindow(event.where, &window);
-
- switch (part)
- {
- case inMenuBar: //process the menu command
- AdjustMenus();
- DoMenuCommand(MenuSelect(event.where));
- break;
-
- case inSysWindow: //let the system handle the mouseDown
- SystemClick(&event, window);
- break;
-
- case inContent:
- // The terminal tool needs to handle selections
- if (!DoToolEvent(event,window))
- {
- if (window != FrontWindow())
- SelectWindow(window);
- else
- if (gTerm != NULL)
- TMClick(gTerm, &event);
- }
- break;
-
- case inDrag: //pass screenBits.bounds to get all gDevices
- if (!DoToolEvent(event,window))
- DragWindow(window, event.where, &qd.screenBits.bounds);
- break;
-
- case inGrow:
- case inZoomIn:
- case inZoomOut:
- case inGoAway:
- DoToolEvent(event,window);
- break;
- }
- break; // case mouseDown
-
- case keyDown:
- case autoKey: //check for menukey equivalents
- window = FrontWindow();
-
- // Get the key
- key = event.message & charCodeMask;
- processed = FALSE;
-
- // The terminal tool might be mapping the cmd key
- // so if menukey fails, send it to the tool
-
- if (((event.modifiers) & cmdKey) != 0)
- {
- AdjustMenus(); //enable/disable/check menu items properly
- result = MenuKey(key);
- if (result != 0) {
- processed = TRUE;
- DoMenuCommand(result);
- }
- }
-
- if ((gTerm != NULL) && !processed)
- if (!DoToolEvent(event, window))
- TMKey(gTerm, &event);
- break;
-
- case activateEvt:
- window = (WindowPtr) event.message;
-
- if (!DoToolEvent(event,window))
- DoActivate(window, ((event.modifiers) & activeFlag) != 0);
- break;
-
- case updateEvt:
- window = (WindowPtr) event.message;
-
- if (!DoToolEvent(event,window))
- DoUpdate(window);
- break;
-
- case diskEvt:
- if (HiWord(event.message) != noErr)
- {
- SetPt(&aPoint, kDILeft, kDITop);
- err = DIBadMount(aPoint, event.message);
- }
- break;
-
- case kOSEvent:
- // Send to frontmost tool window && all tools
- // as this is an application-wide event
-
- switch((event.message >> 8) & 0xFF) //high byte of message
- {
- case kSuspendResumeMessage:
- DoToolEvent(event,FrontWindow());
- gInBackground = ((event.message & kResumeMask) == 0);
- DoResume(!gInBackground);
- break;
- }
- break;
- }
- } //DoEvent
-
-
- /*******************************************************************
- * DoIdle - Idles all the tools
- *
- **********************************************************************/
- #pragma segment Main
- pascal void DoIdle(void)
- {
- WindowPtr theWindow; // The target to idle
- Boolean doFT; // route data to FT Tool
- Boolean doTM; // route data to Term Tool
- GrafPtr savedPort; // for later reset
-
- GetPort(&savedPort); // Save for later
- theWindow = FrontWindow(); // Gimme the first one
-
- // Give idle time for the window
- while (theWindow != NULL)
- {
- if (IsAppWindow(theWindow))
- {
- SetPort(theWindow); // Focus on it
-
- if (gConn != NULL) // Give time to the connection
- CMIdle(gConn);
-
- doFT = FALSE; // Send data to FT tool
- doTM = TRUE; // Send data to terminal tool
-
- if (gFT != NULL)
- {
- // Is there a file transfer in progress ??
- if ((((*gFT)->flags) & ftIsFTMode) != 0)
- {
- doFT = TRUE;
- gWasFT = TRUE;
-
- // If the FT tool uses my connection then
- // don't route data to the terminal tool
-
- if ((((*gFT)->attributes) & ftSameCircuit) != 0)
- doTM = FALSE;
- } // In progress
- else
- {
- if (gWasFT)
- {
- // FT no longer in progress
- gWasFT = FALSE;
-
- // FT tool will alert the user
- if (((*gFT)->flags & ftSucc) == 0)
- ;
-
- // The old search was removed for the transfer
- // so we need to re-add it here
- AddFTSearch();
- }
-
- // AutoReceive string was received ?
- if (gStartFT)
- DoReceive();
- } // No FT in progress
-
- if (doFT) // Give time to FT tool
- FTExec(gFT);
- } // Good FT Handle
-
- if (gTerm != NULL)
- {
- TMIdle(gTerm); // So it can blink its cursor, etc
-
- if (doTM)
- TermRecvProc(); // Send Data to the terminal
- } // Good Terminal
-
- } // App Window
-
- // Try the next window
- theWindow = (WindowPtr) ((WindowPeek) theWindow)->nextWindow;
-
- } // while each window
-
- SetPort(savedPort); // Back to the way it was
-
- } // DoIdle
-
-
- /*******************************************************************
- * EventLoop - The main event loop
- *
- *******************************************************************/
- #pragma segment Main
- pascal void EventLoop(void)
- {
- Boolean gotEvent;
- EventRecord event;
-
- //loop forever; we quit through an ExitToShell
- while (TRUE)
- {
- DoIdle();
-
- if (gHasWaitNextEvent) // put us 'asleep' forever under MultiFinder
- gotEvent = WaitNextEvent(everyEvent, &event, 0, NULL);
- else
- {
- SystemTask(); // must be called if using GetNextEvent
- gotEvent = GetNextEvent(everyEvent, &event);
- }
-
- if (gotEvent)
- {
- AdjustCursor(event.where); //make sure we have the right cursor
- DoEvent(event);
- }
-
- AdjustCursor(event.where);
- }
- } //EventLoop
-
-
- #pragma segment Main
- main()
- {
- MaxApplZone(); // expand the heap so code segments load at the top
- Initialize(); // initialize the program
- EventLoop(); // call the main event loop
- }
-